iT邦幫忙

0

克服 JS 的奇怪部分:call()、bind()、apply()

  • 分享至 

  • xImage
  •  

這次一樣來分享來自"克服 JS 的奇怪部分"的學習筆記,這次要來介紹的是控制函數的方法。
先前我們須知道函數就是一個特殊形態的物件,他有可有可無的名稱屬性,還有可以被呼叫的程式屬性。
而所有函數都擁有call()、bind()、apply()這些方法。

首先,在person的部分,我們知道this會指向當前的層級的位址,也就是person這個物件,而在logName我們會指向全域物件,發現找不到getFullName這個方法,故會報錯。

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() { 
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
}
var logName = function(lang1, lang2) {
    console.log('Logged: ' + this.getFullName());
}
logName();

那如果我們可以控制this指向誰不是很好嗎?

bind() : Function.prototype.bind(),利用bind來控制this指向誰,可傳入物件、函數,他會建立一個新函式並返回。該新函式被呼叫時,會將 this 關鍵字設為給定的參數Product.bind(color);,color就會是this指向的東西。

所以,我們以logName使用bind方法,去複製擁有getFullName函式的person物件,由於他會回傳一個新的函數,所以我們創建一個新的變數logPersonName存取新的函數,並且呼叫他

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {
        
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
        
    }
}

var logName = function(lang1, lang2) {

    console.log('Logged: ' + this.getFullName());
    console.log('Arguments: ' + lang1 + ' ' + lang2);
    console.log('-----------');
    
}

var logPersonName = logName.bind(person);
logPersonName('en');

Logged: John Doe
Arguments: en undefined
-----------

call() : Function.prototype.call,Product.call(this, name, price);第一個參數是this要指向的東西,而後為我們傳入的參數,與bind不同,他並不會創建一個新的函數,call會直接執行,直接決定this指向誰。

可以發現,使用call他會直接執行,並且是可以傳入參數的。

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {    
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;   
    }
}

var logName = function(lang1, lang2) {
    console.log('Logged: ' + this.getFullName());
    console.log('Arguments: ' + lang1 + ' ' + lang2);
    console.log('-----------');
}
logName.call(person, 'en', 'es');

Logged: John Doe
Arguments: en es
-----------

apply() : 與call()所有語法大致上與apply()相同,他們基本上不同處只有 call() 接受一連串的參數,而 apply() 接受單一的array作為參數,如Product.apply(color,['big','slim'])。

很明顯跟call是非常相似,差別在於傳入的參數型態。

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {    
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;   
    }
}

var logName = function(lang1, lang2) {
    console.log('Logged: ' + this.getFullName());
    console.log('Arguments: ' + lang1 + ' ' + lang2);
    console.log('-----------');
}
logName.apply(person, ['en', 'es']);

但我們在實際應用用的到apply嗎?

函數借用(function borrowing),可以借用其他物件的方法,如同我們真的有它本身的屬性。

也就是我們可以使用其他物件方法,就好像我們本身有它的屬性一樣。

var person = {
    firstname: 'John',
    lastname: 'Doe',
    getFullName: function() {    
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;   
    }
}
var person2 = {
    firstname: 'Jane',
    lastname: 'Doe'
}

console.log(person.getFullName.apply(person2));

Jane Doe

function currying,利用bind建立一個新複製的函數,並設定預設參數。

我們所給予的參數,會設定為複製函數的永久參數,multipleByTwo第一個參數設為2,那我們我的a永遠就等於2,如同在 multiply函數中return a * b 前面新增var a = 2,而當我們設置兩個參數,在呼叫時也傳入參數,那麼我們呼叫時,傳入的參數將會失效,一樣是取我們原本設置的兩個參數。

function multiply(a, b) {
    return a*b;   
}

var multipleByTwo = multiply.bind(this, 2);
console.log(multipleByTwo(4)); // 8

var multipleByThree = multiply.bind(this, 3, 2);
console.log(multipleByThree(4)); // 6

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言